Linux键盘输入读取

您所在的位置:网站首页 linux 读取数据 Linux键盘输入读取

Linux键盘输入读取

#Linux键盘输入读取| 来源: 网络整理| 查看: 265

1. 找到键盘设备

linux的键盘设备在 /dev/input/eventX 中,通过 ls /dev/input 通常会看到很多个eventX ls /dev/input 那么哪个才是键盘?继续使用指令 cat /proc/bus/input/devices 查看各个设备的描述,通过关键字 keyboard 可以定位到 event1 cat /proc/bus/input/devices

2. 读取按键

按照linux “一切皆文件” 的特点,读取按键只需三步,open、read和解析,特别注意的是读取的数据为 struct input_event 结构

#include ... ... struct input_event key_info; ... ... if (read(fd, &key_info, sizeof(struct input_event)) > 0) { //这是按键事件 if (key_info.type == EV_KEY) //是哪个按键 及 按键状态 printf("按键: %d 状态: %d \r\n", key_info.code, key_info.value); } key_info.code 是按键对应的标号,比如数字键1对应标号为2,具体对应可以在 linux/input.h 中查看(下面给出一段截图),或者把要用的按键都按一遍打印出来就知道了;key_info.value 是按键状态,只有三种数值,0/松开 1/按下 2/按住(按住不放会连续触发这个事件);特别注意的是,当已经有按键(假设按键a)处于 2/按住 状态时,再去按别的按键(假设按键b),会先读到按键b的 1/按下 事件,而按键a的 2/按住 事件将不再触发,如果继续按住b不放会连续触发按键b的 2/按住 事件,而按键a只会在松开时触发 0/松开 事件;如果有更多的按键同时操作,逻辑同上。 在这里插入图片描述 3. 代码示例

鉴于前面提到的多按键同时按下会掩盖掉前面按键的 2/按住 事件问题,以下代码对 2/按住 事件进行了自行管理,可自行定义最大同时按下按键数和连续触发间隔。

key.h #ifndef _KEY_H_ #define _KEY_H_ /* * 如何确认键盘在"/dev/input/event"几号? * 通过"cat /proc/bus/input/devices"可以看到"keyboard"所在的event号 */ #define INPUT_DEV_PATH "/dev/input/event1" /* * 按键回调注册 * 参数: * obj: 用户私有指针,会在互调的时候传回给用户 * callback: 回调函数原型 void callback(void *obj, int key, int type) * 回调函数参数: * obj: 前面传入的用户私有指针 * key: 键位,可以看头文件中的定义,或者先测试打印一遍就知道哪个按键对哪个值了 * type: 按键状态,0/松开时,1/按下时,2/一直按住(会反复触发回调,间隔多久我也忘了) * 返回: 0/成功 -1/失败,找不到设备或者没有sudo运行 */ int key_register(void *obj, void (*callback)(void *, int, int)); #endif key.c #include #include #include #include #include #include #include #include "key.h" //支持最大同按下的按键数量 #define KEY_COMBINATION 10 //长按按键时会反复触发事件,这里设置时间间隔ms,为0时不触发长按事件 #define KEY_HOLD_EVENT_INTERVALMS 50 //本地主结构体 typedef struct { int fd; void *obj; void (*callback)(void *, int, int); } Key_Struct; //回调线程传入参数结构体(就是把一堆参数打包成一个好传递) typedef struct { void *obj; int key; int type; void (*callback)(void *, int, int); //数组指针 int *combin; } Key_Param; //延时工具 #include void key_delayms(unsigned int ms) { struct timeval tv; tv.tv_sec = ms / 1000; tv.tv_usec = ms % 1000 * 1000; select(0, NULL, NULL, NULL, &tv); } //抛线程工具 static void throwOut_thread(void *obj, void (*callback)(void *)) { pthread_t th; pthread_attr_t attr; //attr init pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //禁用线程同步, 线程运行结束后自动释放 //抛出线程 pthread_create(&th, &attr, (void *)callback, (void *)obj); //attr destroy pthread_attr_destroy(&attr); } //回调线程,在这里回调用户传入的callback函数 static void key_callback(void *argv) { Key_Param *kp = (Key_Param *)argv; do { //按键事件回调 if (kp->callback) kp->callback(kp->obj, kp->key, kp->type); //该值为0时,不触发长按事件 if (KEY_HOLD_EVENT_INTERVALMS > 0) { //按下事件,经过2倍延时后切换为长按事件 if (kp->type == 1) { key_delayms(KEY_HOLD_EVENT_INTERVALMS * 2); kp->type = 2; } //长按事件 else if (kp->type == 2) key_delayms(KEY_HOLD_EVENT_INTERVALMS); } //周期触发长按事件 } while (kp->type == 2 && kp->combin[0] == kp->key); free(kp); } //数组元素的设置和清除,返回位置 static int _arrayAdd(int *array, int len, int value) { int i; for (i = 0; i array[i] = value; return i; } } return 0; } static int _arrayClear(int *array, int len, int value) { int i; for (i = 0; i array[i] = 0; return i; } } return 0; } static void key_thread(void *argv) { Key_Struct *ks = (Key_Struct *)argv; Key_Param *kp; struct input_event key_info; int order; int combin[KEY_COMBINATION] = {0}; while (1) { //阻塞读 if (read(ks->fd, &key_info, sizeof(struct input_event)) > 0) { //这是按键类事件(触屏类事件也是这样读的) if (key_info.type == EV_KEY) { if (!ks->callback || key_info.value > 1) continue; //按键按下时注册到数组,释放时清除 order = 0; if (key_info.value == 1) order = _arrayAdd(combin, KEY_COMBINATION, key_info.code); else _arrayClear(combin, KEY_COMBINATION, key_info.code); //参数准备 kp = (Key_Param *)calloc(1, sizeof(Key_Param)); kp->obj = ks->obj; kp->key = key_info.code; //键位 kp->type = key_info.value; //键值 kp->callback = ks->callback; kp->combin = &combin[order]; //抛线程,在异步线程中触发用户回调函数 throwOut_thread(kp, &key_callback); } } } } /* * 按键回调注册 * 参数: * obj: 用户私有指针,会在互调的时候传回给用户 * callback: 回调函数原型 void callback(void *obj, int key, int type) * 回调函数参数: * obj: 前面传入的用户私有指针 * key: 键位值,可以看中的定义,或者先测试打印一遍就知道哪个按键对哪个值了 * type: 按键状态,0/松开时,1/按下时,2/一直按住(会反复触发回调) * 返回: 0/成功 -1/失败,找不到设备或者没有sudo运行 */ int key_register(void *obj, void (*callback)(void *, int, int)) { Key_Struct *ks; //关键参数检查 if (!callback) return -1; //只读打开键盘所在input设备 int fd = open(INPUT_DEV_PATH, O_RDONLY); if (fd printf("key/%d type/%d\r\n", key, type); } int main(void) { key_register(NULL, &key_callback); while(1) sleep(1); return 0; } 编译: gcc -o out main.c key.c -lpthread运行: sudo ./out (由于打开 /dev/input/event1 需要管理员权限) 推荐文章

https://blog.csdn.net/lanmanck/article/details/8423669



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3